package com.cn.demo.redis;

import org.redisson.Redisson;
import org.redisson.api.RScript;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.LongCodec;
import org.redisson.config.Config;

import java.util.Arrays;

/**
 * 分布式锁
 *
 * @author wangjf
 * @version 1.0
 * @createDate 2019/12/20 15:01
 * @projectName demo
 */
public class RedisDistributedLock {

    /**
     * 获取redis连接
     *
     * @param
     * @return org.redisson.api.RedissonClient
     * @author: wangjf
     * @createTime: 2019/12/20 15:25
     */
    public RedissonClient getRedisson() {
        Config config = new Config();
        config.useSingleServer()
                .setTimeout(1000000)
                .setAddress("redis://192.168.199.32:16380")
                .setPassword("123456");

        RedissonClient redisson = Redisson.create(config);

        return redisson;
    }


    /**
     * 获取锁
     *
     * @param lockName
     * @param expireTime
     * @param clientId
     * @return boolean
     * @author: wangjf
     * @createTime: 2019/12/20 15:04
     */
    public boolean tryLock(String lockName, int expireTime, String clientId) {

        String script = "local lock_key = 'lock:' .. KEYS[1]; " +
                "local reqId = KEYS[2]; " +
                "local expire_time = tonumber(ARGV[1]); " +
                "local is_exists = redis.call('EXISTS', lock_key ); " +
                "if is_exists==1 then " +
                " return 1; " +
                "else " +
                " redis.call('SET', lock_key , reqId);" +
                " redis.call('EXPIRE', lock_key , expire_time);" +
                " return 0; " +
                "end";

        Long result = getRedisson().getScript(LongCodec.INSTANCE).eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.INTEGER, Arrays.asList(lockName, clientId), expireTime);
        return result != 1;
    }

    /**
     * 释放锁
     *
     * @param lockName
     * @param clientId
     * @return void
     * @author: wangjf
     * @createTime: 2019/12/20 15:06
     */
    public void releaseLock(String lockName, String clientId) {

        String script = "local lock_key = 'lock:' .. KEYS[1]; " +
                "local reqId = KEYS[2]; " +
                "local lock_value = redis.call('GET', lock_key ); " +
                "if lock_value==reqId then " +
                " redis.call('DEL',lock_key); " +
                "end";

        getRedisson().getScript().eval(RScript.Mode.READ_WRITE, script, RScript.ReturnType.VALUE, Arrays.asList(lockName, clientId));
    }


    public static void main(String[] args) {

        RedisDistributedLock lock = new RedisDistributedLock();

        boolean b = lock.tryLock("ll", 60, "cc2");
        System.out.println(b);
        lock.releaseLock("ll", "cc2");

    }


}
